package com.zlkj.sms.util;

import cn.hutool.core.codec.Base64;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Autowired;

import java.awt.image.BufferedImage;

/**
 * @author lzw
 * @description 视频配置实体
 * @date 2021/1/21
 */
@Data
@Slf4j
public class VideoPlay extends Thread {

    /**
     * ffmpeg拉取流对象
     */
    private FFmpegFrameGrabber grabber;

    @Autowired
    private VideoPlayWebSocket ws;

    private String rtspUrl = "";
    private String serialId = "0";

    private int width = 600;
    private int height = 400;

    private boolean pushState = false;

    public VideoPlay(String rtspUrl, String serialId, int width, int height){
        this.rtspUrl = rtspUrl;
        this.serialId = serialId;
        this.width = width;
        this.height = height;
        this.grabber = pull(rtspUrl, width, height);
    }

    @Override
    public void run() {
        this.pushState = true;
        this.push();
    }

    /**
     * 开始拉取原视频流
     * @param rtspUrl
     * @param width
     * @param height
     * @return
     */
    public FFmpegFrameGrabber pull(String rtspUrl, int width, int height){
        try{
            FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
            grabber.setOption("rtsp_transport", "tcp");
            grabber.setFrameRate(25D);
            grabber.setImageWidth(width);
            grabber.setImageHeight(height);
            grabber.setVideoBitrate(2_000_000);
            grabber.start();

            return grabber;
        }catch (Exception e){
            log.error("pull stream exception:", e.getMessage());
        }
        return null;
    }

    /**
     * 向web端推流
     */
    public void push(){
        FFmpegFrameGrabber grabber = this.grabber;
        Java2DFrameConverter converter = new Java2DFrameConverter();
        while (this.pushState) {
            try {
                if (null == grabber) {
                    grabber = pull(this.rtspUrl, this.width, this.height);
                    this.grabber = grabber;
                }

                if (VideoPlayWebSocket.count > 0) {
                    Frame frame = grabber.grabImage();
                    if (null == frame) {
                        log.error("video play lose data, device code:", this.serialId);
                        continue;
                    }

                    BufferedImage image = converter.getBufferedImage(frame);
                    byte[] bytes = Tools.bufferedImageToBytes(image);

                    //发送图片帧
                    VideoPlayWebSocket.sendMessage(this.serialId, Base64.encode(bytes));
                } else {
                    this.pushState = false;
                }
            } catch (Exception e) {
                log.error("push stream exception:", e.getMessage());
            }
        }

        try{
            grabber.stop();
            grabber.release();
            this.grabber = null;
            log.error("stop video play =======================================");
        } catch (Exception e){
            log.error("push stream exception:", e.getMessage());
        }
    }
}
